package org.jeecg.modules.system.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.MinioUtil;
import org.jeecg.common.util.RestUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.aliyun.AuditImageUtil;
import org.jeecg.modules.oss.entity.OssFile;
import org.jeecg.modules.oss.service.IOssFileService;
import org.jeecg.modules.system.util.RandImageUtil;
import org.jeewx.api.core.util.DateUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

/**
 * 文件上传
 * @author: jeecg-boot
 */
//@Api(tags="105文件上传")
@Slf4j
@RestController
@RequestMapping("/sys/upload")
public class SysUploadController {
    @Autowired
    private IOssFileService ossFileService;

    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    /**
     * 本地：local minio：minio 阿里：alioss
     */
    @Value(value="${jeecg.uploadType}")
    private String uploadType;

/*
    @ApiOperation(value="文件上传", notes="身份证照片，普通文件")
    @ResponseBody
    @PostMapping("/upload")
    public R upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        String fileName =  DateUtils.getCurrentDateTimeStr("yyyyMMddHHmmssSSS") +"-"+file.getOriginalFilename();
        Map<String,Object> map = new HashMap<>();
        //if (!fileType(fileName)){
           // return R.error("请上传图片,目前只支持图片");
        //}
        try {
            FileUtil.uploadFile(file.getBytes(), config.getUploadPath(), fileName);
            map.clear();
            map.put("fileName",fileName);
            return R.ok(map);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
    }
    @ApiOperation(value="头像上传,参数imgData:base64编码", notes="头像上传")
    @ResponseBody
    @PostMapping("/uploadHead")
    public R uploadHead(@RequestBody Map<String,String> map) {
        String fileName =  DateUtils.getCurrentDateTimeStr("yyyyMMddHHmmssSSS");
        String strBase64 = map.get("imgData");
        String id = String.valueOf(Math.round(Math.random()*100));//map.get("id");
        if(strBase64 != "" && id!= ""){
            fileName =  fileName +"-"+id +".jpg";
        }
        try {
            byte[] bytes = FileUtil.base64ToByte(strBase64);
            if(bytes == null){
                return R.error("Base64编码转换失败");
            }
            FileUtil.uploadFile(bytes, config.getUploadPath(), fileName);
            map.clear();
            map.put("fileName",fileName);
            return R.ok(map);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
    }
*/
    /**
     * 文件上传统一方法
     * @param mtFile
     * @return
     */
    @ApiOperation(value="文件上传", notes="也可以上传图片，参数：MultipartFile")
    @PostMapping(value = "/upload")
    public Result<?> upload(@RequestPart(name="file",required = true) MultipartFile mtFile,
                            HttpServletRequest request, HttpServletResponse response) throws Exception {
        Result<String> result = new Result<>();
        String dbpath = "";
        try {
            String ctxPath = uploadpath;
            String fileName = null;
            String nowday = DateUtils.date2Str(org.jeecg.common.util.DateUtils.yyyyMMdd.get());
            File file = new File(ctxPath + File.separator + nowday + File.separator );
            if (!file.exists()) {
                // 创建文件根目录
                file.mkdirs();
            }
            // 获取文件名
            String orgName = mtFile.getOriginalFilename();
            orgName = CommonUtils.getFileName(orgName);
            if(orgName.indexOf(SymbolConstant.SPOT)!=-1){
                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
            }else{
                fileName = orgName+ "_" + System.currentTimeMillis();
            }
            String savePath = file.getPath() + File.separator + fileName;
            File savefile = new File(savePath);
            FileCopyUtils.copy(mtFile.getBytes(), savefile);
            dbpath = nowday + File.separator + fileName;
            if (dbpath.contains(SymbolConstant.DOUBLE_BACKSLASH)) {
                dbpath = dbpath.replace(SymbolConstant.DOUBLE_BACKSLASH, SymbolConstant.SINGLE_SLASH);
            }

            String checkfile = RestUtil.getBaseUrl()+"/sys/common/static/"+URLEncoder.encode(dbpath, "UTF-8");
            String check = AuditImageUtil.auditImageByAliyun(checkfile);
            if(oConvertUtils.isNotEmpty(check)&&!check.equals("pass")){
                if(savefile.exists()){
                    savefile.delete();
                }
                return(result.error("上传内容审核失败！"));
            }

        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }

        if(oConvertUtils.isNotEmpty(dbpath)){
            result.setResult(dbpath);
            result.success("上传成功！");
        }else {
            result.error("上传失败！");
        }
        return result;
    }

    @ApiOperation(value="多图片base64上传", notes="json参数:{'data':[{'imgName':'head1.jpg','imgData':'base64编码'},{'imgName':'head2.jpg','imgData':'base64编码'}]}")
    @PostMapping("/uploadImgs")
    public Result<?> uploadImgs(@RequestBody JSONObject jsonObject){
        Result<String> result = new Result<String>();
        Map<String,String> map = new HashMap<String,String>();
       /* Set set = map.keySet();
        Iterator it = set.iterator();
        //通过判断是否存在下一个，来遍历map集合
        while(it.hasNext()){
            String key = (String) it.next();
            String value = map.get(key);
        }*/
        JSONArray jsonArray = jsonObject.getJSONArray("data");
        StringBuffer sb = new StringBuffer();
        StringBuffer sbFailed = new StringBuffer();
        String dbpaths = "";
        String dbFailed ="";

        if(jsonArray!=null && jsonArray.size()>0){
            for(int i=0;i<jsonArray.size();i++){
            JSONObject jsonObj= jsonArray.getJSONObject(i);
                String orgName =  jsonObj.getString("imgName");
                String imgData = jsonObj.getString("imgData");
                map.clear();
                map.put("imgName",orgName);
                map.put("imgData",imgData);
                String dbpath = uploadOneImg(map);
                if(oConvertUtils.isNotEmpty(dbpath))
                    sb.append(dbpath).append(",");
                else
                    sbFailed.append(orgName).append(",");
            }
        }
        if(sb.lastIndexOf(SymbolConstant.COMMA)>0){
            dbpaths = sb.deleteCharAt(sb.length() - 1).toString();
        }
        if(sbFailed.lastIndexOf(SymbolConstant.COMMA)>0){
            dbFailed = sb.deleteCharAt(sbFailed.length() - 1).toString();
        }
        if(oConvertUtils.isNotEmpty(dbpaths)&&oConvertUtils.isEmpty(dbFailed)){
            result.setResult(dbpaths);
            result.success("上传成功！");
        }else {
            result.error("上传失败,"+sbFailed);
        }

        return result;
    }

    @ApiOperation(value="图片base64上传", notes="例如头像上传,json参数:{'imgName':'head.jpg','imgData':'base64编码'}")
    @ApiImplicitParam(name = "map" ,value = "Map泛型",paramType = "body", examples = @Example({
            @ExampleProperty(value = "{'imgName':'head.jpg','imgData':'base64编码'}", mediaType = "application/json")
    }))
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "imgName", dataType = "string", paramType = "form", example = "head.jpg", required = true),
//            @ApiImplicitParam(name = "imgData", dataType = "string", paramType = "form", example = "base64编码", required = true)
//    })
    @PostMapping("/uploadImg")
    public Result<?>  uploadImg(@RequestBody Map<String,String> map)  {
        Result<String> result = new Result<String>();
        String dbpath = uploadOneImg(map);
        if(oConvertUtils.isNotEmpty(dbpath)){
            result.setResult(dbpath);
            result.success("上传成功！");
        }else {
            result.error("上传失败！");
        }
        return result;
    }

    private String uploadOneImg(Map<String,String> map){
        String ctxPath = uploadpath;
        String fileName = null;
        String dbpath = null;
        try {
            String nowday = DateUtils.date2Str(org.jeecg.common.util.DateUtils.yyyyMMdd.get());
            File file = new File(ctxPath + File.separator + nowday + File.separator );
            if (!file.exists()) {
                // 创建文件根目录
                file.mkdirs();
            }
            String orgName =  map.get("imgName");
            String strBase64 = map.get("imgData");
            if(orgName.indexOf(SymbolConstant.SPOT)!=-1){
                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
            }else{
                fileName = orgName+ "_" + System.currentTimeMillis();
            }
            String savePath = file.getPath() + File.separator + fileName;
            File savefile = new File(savePath);

            byte[] bytes = RandImageUtil.base64ToByte(strBase64);
            FileCopyUtils.copy(bytes, savefile);
            dbpath = nowday + File.separator + fileName;
            if (dbpath.contains(SymbolConstant.DOUBLE_BACKSLASH)) {
                dbpath = dbpath.replace(SymbolConstant.DOUBLE_BACKSLASH, SymbolConstant.SINGLE_SLASH);
            }

        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        if(oConvertUtils.isNotEmpty(dbpath)){
            return dbpath;
        }else {
            return "";
        }
    }

    /**
     * 上传
     * @param request
     */
    @PostMapping(value = "/uploadMinio")
    public Result<?> uploadMinio(HttpServletRequest request) throws Exception {
        Result<?> result = new Result<>();
        String bizPath = request.getParameter("biz");

        //LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
        boolean flag = oConvertUtils.isNotEmpty(bizPath) && (bizPath.contains("../") || bizPath.contains("..\\"));
        if (flag) {
            throw new JeecgBootException("上传目录bizPath，格式非法！");
        }

        if(oConvertUtils.isEmpty(bizPath)){
            bizPath = "";
        }
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        // 获取上传文件对象
        MultipartFile file = multipartRequest.getFile("file");
        // 获取文件名
        String orgName = file.getOriginalFilename();
        orgName = CommonUtils.getFileName(orgName);
        String fileUrl =  MinioUtil.upload(file,bizPath);
        if(oConvertUtils.isEmpty(fileUrl)){
            return Result.error("上传失败,请检查配置信息是否正确!");
        }
        //保存文件信息
        OssFile minioFile = new OssFile();
        minioFile.setFileName(orgName);
        minioFile.setUrl(fileUrl);
        ossFileService.save(minioFile);
        result.setMessage(fileUrl);
        result.setSuccess(true);
        return result;
    }
}
